package com.example.myapplication;

import android.util.Log;

public class CRC16Modbus {

    // 多项式，表示为不带最高位1的16进制数
    private static final int POLYNOMIAL = 0xA001; // 0x8005左移一位，因为最高位隐含为1
    // 初始值
    private static final int INITIAL_VALUE = 0xFFFF;
    // 异或值，对于CRC-16/MODBUS，最终CRC值不需要异或处理，因此这里用0
    private static final int XOR_OUT = 0x0000;

    /**
     * 计算CRC-16/MODBUS
     *
     * @param string 需要计算CRC的数据字节数组
     * @return CRC-16/MODBUS校验值
     */
    public static String crc16Modbus(String string) {
        // 去除所有空格
        String cleanedString = string.replaceAll("\\s+", "");

        // 确保字符串是按每两个字符分割并有空格
        StringBuilder formattedString = new StringBuilder();

        // 将每两个字符分割，并以空格分隔
        for (int i = 0; i < cleanedString.length(); i += 2) {
            if (i > 0) {
                formattedString.append(" ");
            }
            formattedString.append(cleanedString, i, i + 2);
        }

        // 将处理后的字符串分割为字节
        String[] bytes = formattedString.toString().split(" ");
        byte[] data = new byte[bytes.length];

        // 将每个十六进制字节字符串转换为字节
        for (int i = 0; i < bytes.length; i++) {
            try {
                data[i] = (byte) (Integer.parseInt(bytes[i], 16));  // 转换为字节
            } catch (NumberFormatException e) {
                Log.d("CRC16Modbus", "无效的输入数据: " + bytes[i]);  // 记录无效数据
                throw e;  // 重新抛出或处理错误
            }
        }

        // 初始化 CRC 值
        int crc = INITIAL_VALUE;

        // 处理每个字节以计算 CRC
        for (byte b : data) {
            crc ^= (b & 0xFF);  // 字节与 CRC 进行异或操作

            // 处理每一位
            for (int j = 0; j < 8; j++) {
                if ((crc & 1) != 0) {  // 如果最低位为 1
                    crc = (crc >>> 1) ^ POLYNOMIAL;  // 右移并异或多项式
                } else {
                    crc = crc >>> 1;  // 否则仅右移
                }
            }
        }

        // 计算 CRC 值，并将其反转为需要的格式
        String crcResult = String.format("%04X", crc ^ XOR_OUT);
        return crcResult.substring(2, 4) + crcResult.substring(0, 2);
    }

}
